﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelRuntimeLibrary
{
    /// <summary>
    /// Represents a static and thread safepseudo-random number generator, 
    /// a device that produces a sequence of numbers that meet certain statistical requirements for randomness.</summary>
    public static class RandomEx
    {
        [ThreadStatic]
        private static Random mLocal;

        private static Random mGlobal = new Random();

        /*///////////////////////////////////////////////////////////////////////////////////*/

        /// <summary>
        /// Check the local Random object, and create new one if it's equal null.
        /// </summary>
        private static void CheckLocal()
        {
            Random inst = mLocal;
            if (inst == null)
            {
                int seed;
                lock (mGlobal)
                    seed = mGlobal.Next();

                mLocal = inst = new Random(seed);
            }
        }


        /// <summary>
        /// Returns a nonnegative random number.</summary>
        /// <returns>A 32-bit signed integer greater than or equal to zero and less than <see cref="F:System.Int32.MaxValue"></see>.</returns>
        public static int Next()
        {
            CheckLocal();

            return mLocal.Next();
        }

        /// <summary>
        /// Returns a nonnegative random number less than the specified maximum.</summary>
        /// <returns>A 32-bit signed integer greater than or equal to zero, and less than maxValue; that is, the range of return values includes zero but not maxValue.</returns>
        /// <param name="maxValue">The exclusive upper bound of the random number to be generated. maxValue must be greater than or equal to zero. </param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">maxValue is less than zero. </exception>
        /// <filterpriority>1</filterpriority>
        public static int Next(int maxValue)
        {
            CheckLocal();

            return mLocal.Next(maxValue);
        }

        /// <summary>
        /// Returns a random number within a specified range.</summary>
        /// <returns>A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.</returns>
        /// <param name="minValue">The inclusive lower bound of the random number returned. </param>
        /// <param name="maxValue">The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue. </param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">minValue is greater than maxValue. </exception>
        /// <filterpriority>1</filterpriority>
        public static int Next(int minValue, int maxValue)
        {
            CheckLocal();

            return mLocal.Next(minValue, maxValue);
        }

        /// <summary>
        /// Fills the elements of a specified array of bytes with random numbers.</summary>
        /// <param name="buffer">An array of bytes to contain random numbers. </param>
        /// <exception cref="T:System.ArgumentNullException">buffer is null. </exception>
        /// <filterpriority>1</filterpriority>
        public static void NextBytes(byte[] buffer)
        {
            CheckLocal();

            mLocal.NextBytes(buffer);
        }

        /// <summary>
        /// Returns a random number between 0.0 and 1.0.</summary>
        /// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
        /// <filterpriority>1</filterpriority>
        public static double NextDouble()
        {
            CheckLocal();

            return mLocal.NextDouble();
        }
    }
}
